const gulp = require('gulp');
const { process } = require('./config/env.config');
const path = require('path');
const lazypipe = require('lazypipe');
const gulp = require("gulp");
const path = require("path");
const lazypipe = require("lazypipe");
const $ = require("gulp-load-plugins");

const sass = require('gulp-sass')(require('sass'));

// 与 Bower 结合使用
const mainBowerFiles = require('main-bower-files');
const browserSync = require('browser-sync').create();

const log = require('fancy-log');

// const imagemin = require("gulp-imagemin");

// 与 Bower 结合使用
const es = require("event-stream");
const log = require("fancy-log");

const isDev = process.env.NODE_ENV === 'development';
const resolve = (dir) => {
  return path.join(__dirname, dir);
};

/**
 * The following tasks did not complete: test
 * Did you forget to signal async completion?
 */
gulp.task('test', () => {
  console.log('Hello World!');
});

// 解决
gulp.task('test1', async () => {
  await console.log('Hello World!');
});

// 官方方法，在不使用文件流的情况下，向task的函数里传入一个名叫done的回调函数，以结束task
gulp.task('test2', done => {
  console.log('Hello World!');
  // done回调函数的作用是在task完成时通知Gulp（而不是返回一个流）
  done();
});
const paths = {
  html: {
    input: resolve('src/**/*.html'),
    output: resolve('dist'),
    // watch: 'src/pug/**/*.pug',
  },
  ejs: {
    input: resolve('src/**/*.{ejs, html}'),
    output: resolve('dist'),
    // watch: 'src/pug/**/*.pug',
  },
  scss: {
    input: resolve('src/**/*.{scss, sass}'),
    output: resolve('dist'),
    // watch: 'src/less/**/*.less',
  },
  js: {
    input: resolve('src/**/*.js'),
    output: resolve('dist/js'),
    // watch: 'src/js/**/*.js',
  },
  cssInject: {
    cssInput: resolve("dist/**/*.css"),
    htmlInput: resolve("dist/**/*.html"),
    output: resolve("dist"),
  },
  images: {
    src: 'src/assets/images/**/*.+(png|jpg|jpeg|gif|svg)',
    dest: 'dist/images/',
    watch: 'src/assets/images'
  },
  clean: {
    input: [resolve('dist'), resolve('rev'), resolve('tmp')],
  },
  copy: {
    input: resolve('src/assets/**/*'),
    output: resolve('dist'),
  },
  favicons: {
    input: resolve('src/assets/images/favicons.png'),
    output: resolve('dist'),
  },
  server: {
    input: resolve('dist'),
  },
};
const cssChannel = lazypipe().pipe(() => {
  if (isDev) {
    return $.postcss([require('autoprefixer')]);
  }
  return $.postcss([
    require('autoprefixer'),
    require('cssnano')({
      preset: 'default',
    }),
  ]);
});
const sassChannel = lazypipe()
  .pipe($.sassGlob)
  .pipe(() => sass().on('error', sass.logError));
const cssChannel = lazypipe()
  // .pipe(() =>
  //   $.base64({
  //     baseDir: "public",
  //     extensions: ["svg", "png", /\.jpg#datauri$/i],
  //     exclude: [/\.server\.(com|net)\/dynamic\//, "--live.jpg"],
  //     maxImageSize: 8 * 1024,
  //     debug: true,
  //   })
  // )
  .pipe(() => {
    if (isDev) {
      return $.postcss([require("autoprefixer")]);
    }
    return $.postcss([
      require("autoprefixer"),
      require("cssnano")({
        preset: "default",
      }),
    ]);
  });
const sassChannel = lazypipe()
  .pipe($.sassGlob)
  .pipe(() => sass().on("error", sass.logError));
const imageChannel = lazypipe().pipe(() => {
  imagemin(
    [
      imagemin.gifsicle({ interlaced: true }),
      imagemin.mozjpeg({ quality: 75, progressive: true }),
      imagemin.optipng({ optimizationLevel: 5 }),
      imagemin.svgo({
        plugins: [{ removeViewBox: true }, { cleanupIDs: false }],
      }),
    ],
    {
      verbose: true,
    }
  );
});

// 打包 HTML
gulp.task('html', () => {
  const { input, output } = paths.html;
  return (
    gulp
      .src(input)
      // 读取文件后面加入 plumber
      .pipe($.plumber())
      .pipe(
        $.if(
          !isDev,
          $.htmlmin({
            removeComments: true, // 清除 HTML 注释
            collapseWhitespace: true, // 压缩空格
            collapseBooleanAttributes: true, // 省略布尔属性的值，如 <input checked='true'/> => <input checked/>
            removeEmptyAttributes: true, // 删除所有空格作属性值，如 <input id=''> => <input>
            removeScriptTypeAttributes: true, // 删除 <script> 的 type='text/javascript' 属性
            removeStyleLinkTypeAttributes: true, // 删除 <style> 和 <link> 的 type='text/css' 属性
            minifyJS: true, // 压缩页面 JavaScript
            minifyCSS: true, // 压缩页面 CSS
          })
        )
      )
      // .pipe(htmlChannel())
      .pipe(gulp.dest(output))
  );
});

gulp.task('js', () => {
  const { input, output } = paths.js;
  return gulp
    .src(input)
    .pipe($.plumber())
    .pipe($.filter('**/src/*.js'))
    .pipe($.eslint())
    .pipe($.eslint.format())
    .pipe($.eslint.failAfterError())
    .pipe($.filter("**/src/*.js"))
    .pipe($.babel())
    // .pipe(concat('main.min.js'))    // 合并文件并命名
    .pipe($.if(!isDev, $.uglify()))
    .pipe(gulp.dest(output));
});

gulp.task('ejs', () => {
  const { input, output } = paths.ejs;
  return gulp
    .src(input)
    .pipe($.plumber())
    .pipe($.filter(['**/src/*.ejs', '**/views/*.ejs']))
    .pipe($.ejs())
    .pipe($.rename({ extname: '.html' }))
    .pipe(gulp.dest(output));
  return (
    gulp
      .src(input)
      .pipe($.plumber())
      .pipe($.filter(["**/src/*.ejs", "**/views/*.ejs"]))
      .pipe($.ejs())
      .pipe(
        $.rename((path) => {
          log(JSON.stringify(path));
          return {
            dirname: path.dirname,
            basename: path.basename,
            extname: ".html",
          };
        })
      )
      // .pipe($.inject(sources))
      .pipe(gulp.dest(output))
      .pipe(browserSync.reload({ stream: true }))
  );
});

gulp.task('scss', () => {
  const { input, output } = paths.scss;
  const filter = $.filter('**/src/*.scss', { restore: true });
  return gulp
    .src(input)
    .pipe($.plumber())
    .pipe(
      $.stylelint({
        failAfterError: true, // 默认 true
        reporters: [{ formatter: "string", console: true }], // 默认 []
        debug: true, // 默认 false
      })
    )
    .pipe(filter)
    .pipe(sassChannel())
    .pipe(cssChannel())
    .pipe(gulp.dest(output))
    .pipe(filter.restore)
    .pipe($.filter('**/views/*.scss'))
    .pipe(sassChannel())
    .pipe(cssChannel())
    .pipe(
      $.rename((path) => {
        log(JSON.stringify(path));
        // 更改Gulp中文件的目标路径(Change the destination path of files in Gulp)
        return {
          dirname: '/css',
          basename: path.basename,
          extname: path.extname,
        };
      })
    )
    .pipe(gulp.dest(output));
});

gulp.task('images', function () {
  const { input, output } = paths.images;
  return gulp
    .src(input)
    .pipe($.plumber())
    .pipe($.if(!isDev, $.cache($.imagemin([
      $.imagemin.options({
        optimizationLevel: 5, // 默认：3 取值范围：0-7（优化等级）
        progressive: true, // 默认：false 无损压缩 jpg 图片
        interlaced: true, // 默认：false 隔行扫描 gif 进行渲染
        multipass: true, // 默认：false 多次优化 svg 直到完全优化
      }),
      $.imagemin.pngquant()
    ]))))
    .pipe(gulp.dest(output))
});

gulp.task('bower', () => {
gulp.task("inject", () => {
  const { htmlInput, cssInput, output } = paths.cssInject;
  return (
    gulp
      .src(htmlInput)
      // .pipe(
      //   es.map((file, cb) => {
      //     log(path.basename(file.path));
      //     log(path.dirname(file.path));
      //     log(path.extname(file.path));
      //     return cb();
      //   })
      // )
      .pipe(
        $.inject(gulp.src(cssInput, { read: false }), {
          relative: true,
          removeTags: true,
          transform: function (filepath, file, index, length, targetFile) {
            const cssName = path.basename(filepath);
            const htmlName = path.basename(targetFile.path);
            if (htmlName.slice(0, -5) === cssName.slice(0, -4)) {
              return $.inject.transform.apply($.inject.transform, arguments);
            }
          },
        })
      )
      .pipe(gulp.dest(output))
  );
});

gulp.task("bower", () => {
  return (
    gulp
      // .src(mainBowerFiles())
      .src(
        mainBowerFiles({
          overrides: {
            vue: {
              // 插件名称
              main: 'dist/vue.js', // 对应的文件路径
            },
          },
        })
      )
      // 输出到临时文件夹 tmp/vendors
      .pipe(gulp.dest('./tmp/vendors'))
  );
});

/**
 * 清空文件夹
 * 因为打包只会覆盖改变的文件，在 src 中删除的文件，在 dist 中会依然存在
 */
gulp.task('clean', () => {
  const { input } = paths.clean;
  return gulp
    .src(input, {
      read: false, // 默认 true
      allowEmpty: true, // 默认 false
    })
    .pipe($.plumber())
    .pipe($.clean())
    .pipe($.notify('Found file: <%= JSON.stringify(file) %>!'));
  // .pipe($.notify('文件已清空!'));
});

gulp.task('copy', () => {
  const { input, output } = paths.copy;
  const cssFilter = $.filter('**/*.css', { restore: true });
  const filter = $.filter(['**', '!*.css']);
  const cssFilter = $.filter("**/*.css", { restore: true });
  const imageFilter = $.filter("**/*.{png, jpg, gif, svg}", { restore: true });
  const filter = $.filter(["**", "!*.css"]);
  return gulp
    .src(input)
    .pipe($.plumber())
    .pipe(imageFilter)
    .pipe(imageChannel)
    .pipe(gulp.dest(output))
    .pipe(imageFilter.restore)
    .pipe(cssFilter)
    .pipe(cssChannel())
    .pipe(gulp.dest(output))
    .pipe(cssFilter.restore)
    .pipe(filter)
    .pipe(gulp.dest(output));
  // .pipe($.notify('拷贝完成!'));
});

gulp.task('favicons', () => {
  const { input, output } = paths.favicons;
  return gulp
    .src(input)
    .pipe(
      $.favicons({
        appName: 'My App',
        appShortName: 'App',
        appDescription: 'This is my application',
        developerName: 'Hayden Bleasel',
        developerURL: 'http://haydenbleasel.com/',
        background: '#020307',
        path: 'favicons/',
        url: 'http://haydenbleasel.com/',
        display: 'standalone',
        orientation: 'portrait',
        scope: '/',
        start_url: '/?homescreen=1',
        version: 1.0,
        logging: false,
        html: 'index.html',
        pipeHTML: true,
        replace: true,
      })
    )
    .pipe(gulp.dest(output));
});

/**
 * 静态服务器
 * [Browsersync] Access URLs:
 * -------------------------------------
 *       Local: http://localhost:3000
 *    External: http://192.168.1.55:3000
 * -------------------------------------
 *          UI: http://localhost:3001
 * UI External: http://localhost:3001
 * -------------------------------------
 * [Browsersync] Serving files from: D:\frontend\gulp-demo\dist
 * 说明:
 * 1. Local: http://localhost:3000
 *    1. 默认打开此服务器地址
 *    2. 默认端口是 3000，如果端口号被占用，则自动打开3001，依次类推
 * 2. External: http://169.254.109.182:3000
 *    1. 此地址可用于手机访问
 *    2. 需要手机调试时，可以访问这个地址，但手机和电脑要在同一 wifi 网络
 */
gulp.task('server', () => {
  const { input } = paths.server;
  browserSync.init({
    server: {
      // 访问目录，其值可以是字符串、对象
      baseDir: input,
      index: 'index.html',
      middleware: [
        // 自定义中间件
        function (req, res, next) {
          console.log('Hi from first middleware');
          next();
        },
        // createProxyMiddleware('/api', {
        //   target: 'http://127.0.0.1:5000',
        //   changeOrigin: true, // for vhosted sites, changes host header to match to target's host
        //   pathRewrite: {
        //     '^/api': '',
        //   },
        //   logLevel: 'debug',
        // }),
      ],
    },
    https: false,
    // proxy: '', // 域名或 ip，设置代理
  });
  gulp
    .watch(["src/**/*.ejs"], gulp.series(["ejs", "inject"]))
    .on("change", browserSync.reload);
});

/**
 * watch 侦听，侦听文件变化，实现自动打包，自动刷新浏览器。
 * 自动打包，要求速度要快，所以
 * 1. 尽可能的将监听任务拆开
 * 2. 减少开发模式下的功耗，如不进行压缩处理，特别是图片的压缩需要时间较长。
 */
gulp.task("watch", () => {
  gulp
    .watch(["src/**/*.ejs"], gulp.series(["ejs", "inject"]))
    .on("change", browserSync.reload);
});

/**
 * 执行顺序
 * Gulp 4.0 及以上版本 gulp.series 顺序执行，gulp.paralle 并行执行
 */
gulp.task(
  'dev',
  gulp.series(
    'clean',
    'copy',
    gulp.parallel(
      // 'favicons',
      'ejs',
      // 'html'
      // 'js',
      'scss'
      // 'css',
      // 'images',
      // 'watch',
      // 'server',
      // 'clean',
      // 'copy'
      // gulp.parallel(
      //   // 'copy',
      //   'html',
      //   'js',
      //   'scss',
      //   'images',
      //   'watch',
      //   'server',
      //   function () {
      //     console.log('gulp start dev');
      //   },
      // ),
    ),
    'server'
    "clean",
    "copy"
    // gulp.parallel(
    // "favicons",
    // "html"
    // "js",
    // "scss",
    // "ejs"
    // "css",
    // "images",
    // "watch",
    // "server",
    // "clean",
    // "copy"
    // gulp.parallel(
    //   // 'copy',
    //   "html",
    //   "js",
    //   "scss",
    //   "images",
    //   "watch",
    //   "server",
    //   function () {
    //     console.log("gulp start dev");
    //   },
    // ),
    // ),
    // "inject",
    // "watch",
    // "server"
  )
);

gulp.task("build", () => {});
